package handler

import (
	"fmt"
	"gitee.com/mangenotwork/game-douniu/api/dao"
	"gitee.com/mangenotwork/game-douniu/api/entity"
	"github.com/mangenotwork/common/ginHelper"
	"github.com/mangenotwork/common/log"
	"github.com/mangenotwork/common/utils"
	"sync"
)

var AdminToken sync.Map

func AdminTokenSet(data *SetAdminTokenReq) {
	AdminToken.Store(data.User, data.Token)
}

func AdminTokenGet(data *SetAdminTokenReq) bool {
	token, ok := AdminToken.Load(data.User)
	if !ok {
		return false
	}
	if data.Token == token {
		return true
	}
	return false
}

type AdminLoginReq struct {
	User     string `json:"user"`
	Password string `json:"password"`
}

type AdminLoginResp struct {
	IsOk int `json:"is_ok"` // 1:登录成功  非1:失败
}

func AdminLogin(c *ginHelper.GinCtx) {
	req := &AdminLoginReq{}
	err := c.GetPostArgs(req)
	if err != nil {
		c.APIOutPutError(nil, err.Error())
		return
	}
	resp := &AdminLoginResp{
		IsOk: 2,
	}
	if new(dao.AdminDao).Login(req.User, req.Password) {
		resp.IsOk = 1
	}
	c.APIOutPut(resp, "ok")
	return
}

type SetAdminTokenReq struct {
	User  string `json:"user"`
	Token string `json:"token"`
}

// 设置管理员登录的token
func SetAdminToken(c *ginHelper.GinCtx) {
	req := &SetAdminTokenReq{}
	err := c.GetPostArgs(req)
	if err != nil {
		c.APIOutPutError(nil, err.Error())
		return
	}
	AdminTokenSet(req)
	c.APIOutPut("", "ok")
	return
}

type HomeDataResp struct {
	UserTotal         int64  `json:"user_total"`            // 用户总数
	NewUserToDayTotal int64  `json:"new_user_to_day_total"` // 今日新增用户数 :
	RoomTotal         int64  `json:"room_total"`            // 游戏房间数 :
	PlayTotal         int64  `json:"play_total"`            // 玩游戏的用户数 :
	ApkVersion        string `json:"apk_version"`           // 游戏版本
	ApkDownload       string `json:"apk_download"`          // 游戏下载地址
	IosVersion        string `json:"ios_version"`           // 游戏版本
	IosDownload       string `json:"ios_download"`          // 游戏下载地址
}

func HomeData(c *ginHelper.GinCtx) {
	resp := &HomeDataResp{
		UserTotal:         new(dao.UserDao).UserCount(),
		NewUserToDayTotal: new(dao.UserDao).NewUserToDayTotal(),
		RoomTotal:         GetRoomTotal(),
		PlayTotal:         GetUserPlayGameTotal(),
	}

	conf, err := new(dao.GameConfDao).Get()
	if err != nil {
		c.APIOutPutError(nil, err.Error())
		return
	}

	resp.ApkVersion = conf.ApkVersion
	resp.ApkDownload = conf.ApkDownload
	resp.IosVersion = conf.IosVersion
	resp.IosDownload = conf.IosDownload

	c.APIOutPut(resp, "ok")
	return
}

type UserListResp struct {
	Total int64           `json:"total"`
	List  []*UserBaseData `json:"list"`
}

type UserBaseData struct {
	UserId    int64  `json:"user_id"`    // 用户id
	Avatar    string `json:"avatar"`     // 头像
	NickName  string `json:"nick_name"`  // 昵称
	CreatedAt string `json:"created_at"` // 注册时间
	Account   string `json:"account"`    // 账号
	IsVip     int64  `json:"is_vip"`     // 是否是VIP   1：是  非1:不是
	OnLine    int64  `json:"online"`     // 是否在线  1：是 非1:不是
	GameCount int64  `json:"game_count"` // 游玩局数
}

func UserList(c *ginHelper.GinCtx) {
	pageStr := c.Query("page")
	page := utils.AnyToInt64(pageStr)
	limitStr := c.Query("limit")
	limit := utils.AnyToInt64(limitStr)
	userIdStr := c.Query("user_id")
	userId := utils.AnyToInt64(userIdStr)
	nickName := c.Query("nick_name")

	count, data, err := new(dao.UserDao).GetUserListByPg(page, limit, userId, nickName)
	if err != nil {
		c.APIOutPutError(nil, err.Error())
		return
	}

	userIds := make([]int64, 0)
	for _, v := range data {
		userIds = append(userIds, v.UserId)
	}

	// todo 获取玩家是否在线, 利用过期缓存实现, 在登录和发牌触发写入在线状态，10分钟

	// 获取玩家游戏局数
	countMap, err := new(dao.GameDao).UserGameCount(userIds)
	if err != nil {
		log.Error(err)
	}

	respList := make([]*UserBaseData, 0)
	for _, v := range data {
		info := &UserBaseData{
			UserId:    v.UserId,
			Avatar:    v.Avatar,                          // 头像
			NickName:  v.NickName,                        // 昵称
			CreatedAt: utils.Timestamp2Date(v.CreatedAt), // 注册时间
			Account:   v.Account,                         // 账号
			IsVip:     v.IsVip,                           // 是否是VIP   1：是  非1:不是
		}
		if countData, ok := countMap[v.UserId]; ok {
			info.GameCount = countData.Num
		}
		respList = append(respList, info)
	}

	resp := &UserListResp{
		Total: count,
		List:  respList,
	}

	c.APIOutPut(resp, "ok")
	return
}

type UserGameDataResp struct {
	GameId     int64  `json:"game_id"`     // 游戏对局ID
	ItemId     int64  `json:"item_id"`     // 轮数
	CreatedAt  string `json:"created_at"`  // 时间
	VsMsg      string `json:"vs_msg"`      // 结果
	Vocation   string `json:"vocation"`    // 庄家闲家
	Score      int64  `json:"score"`       // 输赢分数
	Balance    int64  `json:"balance"`     // 基数
	Multiple   int64  `json:"multiple"`    // 倍数
	AllScore   int64  `json:"all_score"`   // 累计输赢
	Poker      string `json:"poker"`       // 我的牌
	RivalId    string `json:"rival_id"`    // 对手用户id
	RivalPoker string `json:"rival_poker"` // 对手的牌
}

// 用户游戏对局详情, 查最近500条
func UserGameList(c *ginHelper.GinCtx) {
	userIdStr := c.Query("user_id")
	userId := utils.AnyToInt64(userIdStr)

	data, err := new(dao.GameDao).UserGameList(userId)
	if err != nil {
		c.APIOutPutError(nil, err.Error())
		return
	}

	rivalIds := make([]int64, 0)
	for _, v := range data {
		rivalIds = append(rivalIds, v.RivalId)
	}

	rivalIds = removeDuplicates(rivalIds)

	rivalMap, err := new(dao.UserDao).GetUserMap(rivalIds)
	if err != nil {
		c.APIOutPutError(nil, err.Error())
		return
	}

	resp := make([]*UserGameDataResp, 0)

	for _, v := range data {
		myPoker, myPokerResult, err := new(dao.GameDao).AnalysisPoker(v.Poker, v.PokerResult)
		if err != nil {
			log.Error(err)
			continue
		}
		myPokerStr := entity.PokerToShow(myPoker) + " - " + myPokerResult.HasNiuStr

		rivalPoker, rivalPokerResult, err := new(dao.GameDao).AnalysisPoker(v.RivalPoker, v.RivalPokerResult)
		if err != nil {
			log.Error(err)
			continue
		}
		rivalPokerStr := entity.PokerToShow(rivalPoker) + " - " + rivalPokerResult.HasNiuStr

		vocation := "闲家"
		if v.Vocation == 1 {
			vocation = "庄家"
		}

		resp = append(resp, &UserGameDataResp{
			GameId:     v.GameId,
			ItemId:     v.ItemId,
			CreatedAt:  utils.Timestamp2Date(v.CreatedAt),
			VsMsg:      v.VSMsg,
			Vocation:   vocation,
			Score:      v.Score,
			Balance:    v.Balance,
			Multiple:   v.Multiple,
			AllScore:   v.AllScore,
			Poker:      myPokerStr,
			RivalId:    fmt.Sprintf("%s(id:%d)", rivalMap[v.RivalId].NickName, v.RivalId),
			RivalPoker: rivalPokerStr,
		})
	}

	c.APIOutPut(resp, "ok")
	return
}

func RoomList(c *ginHelper.GinCtx) {

	resp := make([]*entity.RoomState, 0)

	Room.Range(func(key, value any) bool {
		resp = append(resp, value.(*entity.RoomState))
		return true
	})
	c.APIOutPut(resp, "ok")
	return
}

func GameConfUpdate(c *ginHelper.GinCtx) {
	req := &entity.GameConf{}
	err := c.GetPostArgs(req)
	if err != nil {
		c.APIOutPutError(nil, err.Error())
		return
	}

	err = new(dao.GameConfDao).Update(req)
	if err != nil {
		c.APIOutPutError(nil, err.Error())
		return
	}
	c.APIOutPut("ok", "ok")
	return
}
